
`include "defines.v"

//----------------------------------------------------------------
//Module Name : csr_unit.v
//Description of module:
// 
//----------------------------------------------------------------
//Designer:	Tang Pengyu
//Date: 2021/08/31	  
//----------------------------------------------------------------

module	csr_unit(
		input	[7:0]	inst_opcode,
		input	[`REG_DATA_LEN-1:0]	extend_imm,				//其中包含了CSR地址
		input	rs1_r_ena,
		input	[4:0] 	rs1_r_addr,
		input	[`REG_DATA_LEN-1:0]	op1,
		input	rd_w_ena,
		input	[4:0]	rd_w_addr,
		input	[`REG_DATA_LEN-1:0]	csr_r_data,
		input	csr_imm_ena,							//csr立即数使能
		input	[`REG_DATA_LEN-1:0]	csr_imm,						//csr立即数
		
		output	[11:0] csr_addr,
		output	reg csr_w_ena,
		output	reg [`REG_DATA_LEN-1:0]	csr_w_data,
		output	reg csr_r_ena
		);

assign	csr_addr = extend_imm[11:0];

wire	[1:0]	csr_rw;			//csr地址[11：10],标志是否可读写
assign	csr_rw = extend_imm[11:10];
//wire	[1:0]	csr_pri;		//csr最低权限
//assign	csr_pri = extend_imm[9:8];
		
always @(*)
  begin
	case(inst_opcode)
		8'b001_11100:						//inst_csrrw
			begin
				csr_r_ena = (rd_w_ena == 1'b0) ? 1'b0 :
							(rd_w_addr == 5'h00) ? 1'b0 : 1'b1;
				csr_w_ena = (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = op1;
			
			end
		8'b010_11100:						//inst_csrrs
			begin
				csr_r_ena = 1'b1;
				csr_w_ena = ((rs1_r_ena == 1'b0) ? 1'b0 :
							(rs1_r_addr == 5'h00) ? 1'b0 : 1'b1)
							& (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = op1 | csr_r_data;
			
			end
		8'b011_11100:						//inst_csrrc
			begin
				csr_r_ena = 1'b1;
				csr_w_ena = ((rs1_r_ena == 1'b0) ? 1'b0 :
							(rs1_r_addr == 5'h00) ? 1'b0 : 1'b1)
							& (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = (~op1) & csr_r_data;
			end
		8'b101_11100:						//inst_csrrwi
			begin
				csr_r_ena = (rd_w_ena == 1'b0) ? 1'b0 :
							(rd_w_addr == 5'h00) ? 1'b0 : 1'b1;
				csr_w_ena = (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = csr_imm;
			end
		8'b110_11100:						//inst_csrrsi
			begin
				csr_r_ena = 1'b1;
				csr_w_ena = ((csr_imm_ena == 1'b0) ? 1'b0 :
							(csr_imm[4:0] == 5'h00) ? 1'b0 : 1'b1)
							& (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = csr_imm | csr_r_data;
			end
		8'b111_11100:						//inst_csrrci
			begin
				csr_r_ena = 1'b1;
				csr_w_ena = ((csr_imm_ena == 1'b0) ? 1'b0 :
							(csr_imm[4:0] == 5'h00) ? 1'b0 : 1'b1)
							& (!(csr_rw[0] & csr_rw[1]));
				csr_w_data = (~csr_imm) & csr_r_data;
			end
		default:
			begin
				csr_r_ena = 1'b0;
				csr_w_ena = 1'b0;
				csr_w_data = 64'd0;
			
			end
    endcase
  end
  
  
endmodule